#ifndef NETLIB_SINGLETON_H
#define NETLIB_SINGLETON_H

// 线程单例类

#include "noncopyable.h"

#include <assert.h>
#include <pthread.h>
#include <stdlib.h>

namespace netlib
{

namespace detail
{

template<typename T>
struct has_no_destroy
{
  template <typename C> static char test(decltype(&C::no_destroy));
  template <typename C> static int32_t test(...);
  const static bool value = sizeof(test<T>(0)) == 1;

}; // class has_no_destroy end

} // namespace detail end

template<typename T>
class Singleton : noncopyable // 不可拷贝
{
public:
    Singleton() = delete;
    ~Singleton() = delete;

    static T& instance() // 返回单例对象，线程安全
    {
        pthread_once(&ponce_, &Singleton::init); // 保证只调用一次
        assert(value_ != NULL);
        return *value_;
    }

    private:
    static void init() // 创建一个对象
    {
        value_ = new T();
        if (!detail::has_no_destroy<T>::value)
            ::atexit(destroy); // 向系统注册一个销毁函数，程序结束自动销毁
    }

    static void destroy() // 销毁一个对象
    {
        //T_must_be_complete_type,防止value_是一个不完全类型从而导致运行时程序崩溃
        typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
        T_must_be_complete_type dummy; (void) dummy;

        delete value_;
        value_ = NULL;
    }

private:
    static pthread_once_t ponce_;       // pthread_once_t保证只初始化一次
    static T*             value_;       // 实际对象的指针

}; // class Singleton end


template<typename T>
pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;

template<typename T>
T* Singleton<T>::value_ = NULL;

} // namespace netlib end

#endif